package it.polito.connectedcar.tcc.zone;

import it.polito.connectedcar.tcc.TCCVehicleAbstraction;

import java.awt.geom.Point2D;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * This class represents a Token which is neighbor of a given Token. a TokenLink
 * is identified by a direction expressed in degree from the magnetic north and
 * a standard deviation from this direction. Is used by a TCC to identify ,
 * given a direction , which is the next-hop Token he knows about.
 * 
 * the TokenLink has got the address of the TCC in charge of managing vehicles
 * contained inside it
 * 
 * @author Nicola Aresta
 * 
 */
public class TokenLink {

	private InetSocketAddress TCCAddress;
	private List<Integer> belongingQuadrants;
	public static final double standardDegreeDeviation = 1;
	private List<TCCVehicleAbstraction> transitVehicles;
	private Point2D upperLeftOutsideRegionPoint;
	private Point2D bottomRightOutsideRegionPoint;
	private Token token;

	public TokenLink(Point2D upperLeftOutsideRegionPoint,
			Point2D bottomRightOutsideRegionPoint,
			InetSocketAddress tccAddress, List<Integer> belongingQuadrants,
			Token token) {
		this();
		this.upperLeftOutsideRegionPoint = upperLeftOutsideRegionPoint;
		this.bottomRightOutsideRegionPoint = bottomRightOutsideRegionPoint;
		this.TCCAddress = tccAddress;
		this.belongingQuadrants = belongingQuadrants;
		this.token = token;
		this.transitVehicles = new CopyOnWriteArrayList<TCCVehicleAbstraction>();
	}

	private TokenLink() {

	}

	/**
	 * given a Vehicle , their TokenLink can be useful for it if: - he belongs
	 * to the owning Zone and he is going toward the TokenLink's zone - he
	 * belongs to the owning Zone and he is in a transit quadrant belonging to
	 * the TokenLink' quadrants - he belongs to the TokenLink's Zone ad it is
	 * directed to the owning Zone.
	 * 
	 * Knwing if a TokenLink is useful or not , allow to prepare the list of all
	 * vehicles outside the Zone's area to give to a certain vehicle
	 * 
	 * @param tva
	 * @return
	 */
	public boolean isUsefulFor(TCCVehicleAbstraction tva) {
		if (tva.getBelongingToken().equals(token)
				&& isInOutsideRegion(tva.getUtmXPos(), tva.getUtmYPos())) {
			return true;
		} else if (tva.getBelongingToken().equals(token)
				&& belongingQuadrants.contains(tva.getCurrentQuadrant())
				&& !isInOutsideRegion(tva.getUtmXPos(), tva.getUtmYPos())) {
			return true;
		} else if (!tva.getBelongingToken().equals(token)
				&& isInOutsideRegion(tva.getUtmXPos(), tva.getUtmYPos())) {
			return true;
		} else
			return false;
	}

	/**
	 * A tokenLink takes into account a region outside the owning Zone which
	 * represents the area toward the Zone represented by the TokenLink
	 * 
	 * @param utmXPos
	 * @param utmYPos
	 * @return
	 */
	private boolean isInOutsideRegion(double utmXPos, double utmYPos) {
		return utmXPos >= upperLeftOutsideRegionPoint.getX()
				&& utmXPos <= bottomRightOutsideRegionPoint.getX()
				&& utmYPos <= upperLeftOutsideRegionPoint.getY()
				&& utmYPos >= bottomRightOutsideRegionPoint.getY();
	}

	/**
	 * 
	 * @return the Address of the TCC managing this Token
	 */
	public InetSocketAddress getTCCAddress() {
		return TCCAddress;
	}

	/**
	 * return the Token identifying the Zone
	 * 
	 * @return
	 */
	public Token getToken() {
		return token;
	}

	/**
	 * The list of all the vehicles which are in transit from the Zone owning
	 * this TokenLink and the Token represented by this TokenLink
	 * 
	 * @return
	 */
	public List<TCCVehicleAbstraction> getTransitVehicles() {
		return transitVehicles;
	}

	/**
	 * the upper-left point describing the outside region toward this tokenLink
	 * starting from the Zone owning the tokenLink itself
	 * 
	 * @return
	 */
	public Point2D getUpperLeftOutsideRegionPoint() {
		return upperLeftOutsideRegionPoint;
	}

	/**
	 * the bottom-right point describing the outside region toward this
	 * tokenLink starting from the Zone owning the tokenLink itself
	 * 
	 * @return
	 */
	public Point2D getBottomRightOutsideRegionPoint() {
		return bottomRightOutsideRegionPoint;
	}

	/**
	 * the list of all the quadrants inside the owning Zone which can
	 * potentially bring to the Zone described by this TokenLink
	 * 
	 * @return
	 */
	public List<Integer> getBelongingQuadrants() {
		return belongingQuadrants;
	}

}
